package com.code;

import org.junit.Test;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;

public class RSACode {

    @Test
    public void test() {
        int p = 47;
        int q = 71;

        int n = p * q;
        int fn = (p - 1) * (q - 1);

        int e = 27;
        int d = Gcd.exGcd(e, fn)[0];

        System.out.println("p=" + p);
        System.out.println("q=" + q);
        System.out.println("n=" + n);
        System.out.println("φ(n)=" + fn);
        System.out.println("e=" + e);
        System.out.println("d=" + d);

    }

    @Test
    public void testpow() {
        int n = 3337;
        int e = 27;
        int d = 2743;

        int m = 2254;
        System.out.println("原文:" + m);

        int c = Pow.powRemainder(m, e, n);
        System.out.println("密文:" + c);

        int cm = Pow.powRemainder(c, d, n);
        System.out.println("解密:" + cm);

    }

    @Test
    public void testBigDecimal() {
        String s = "1230186684530117755130494958384962720772853569595334792197322452151726400507263657518745202199786469389956474942774063845925192557326303453731548268507917026122142913461670429214311602221240479274737794080665351419597459856902143413";
        BigDecimal bigDecimal = new BigDecimal(s);
        Double c = Math.log(123) * 230;
        Integer cc = c.intValue();
        BigDecimal bc = new BigDecimal(cc.toString());
        System.out.println(bigDecimal.divide(bc, 0, BigDecimal.ROUND_HALF_UP).pow(2).toString().length());

    }

    /**
     * 质数数量x/ln(x)
     * 变换一下 2^x/ln(2^x)
     * 得出 2^x/xln(2)
     */
    @Test
    public void testPrimeSize() {
        int x = 128;
        BigInteger b1 = new BigInteger("1");
        //将1左移128位 得到129位的100000...00000，再减1，得到128位能表示的最大无符号的数 1111111...11111
        BigInteger b128 = b1.shiftLeft(x).subtract(b1);
        //计算xln(2)，Math.log就是ln
        double xln2 = x * Math.log(2);

        //转换BigDecimal
        BigDecimal bd128 = new BigDecimal(b128);
        BigDecimal bxln2 = new BigDecimal(xln2);

        //计算出小于x的质数个数
        BigInteger size = bd128.divide(bxln2, 0, RoundingMode.HALF_UP).toBigInteger();
        System.out.println(x + "位内的质数个数：" + size);

        //假设平均存储占用x/2个bit
        int k = x / 2;
        //存储x内的质数所需空间，单位bit
        BigInteger bitSize = size.multiply(BigInteger.valueOf(k));
        //转换为PB，PB系数 1024tb * 1024gb * 1024mb * 1024kb * 1024byte * 8bit
        //1024L*1024*1024*1024*1024*8 实际就是2的 10*5+3
        BigInteger pbSize = bitSize.divide(b1.shiftLeft(10 * 5 + 3));
//        System.out.println(bitSize);
        System.out.println("存储所需空间PB:" + pbSize + "  十进制位数：" + pbSize.toString().length());

        //bdp京东零售大数据集市配额11254200 PB 一千多万PB
        BigInteger jdlPB = new BigInteger("11254200");

        BigInteger jdlSize = pbSize.divide(jdlPB);

        //大概两万多亿亿个京东零售集市
        System.out.println("存储所需京东零售集市个数：" + jdlSize + "  十进制位数："+jdlSize.toString().length());


    }


    @Test
    public void testLength() {

        BigInteger f1 = new BigInteger("1");

        BigInteger bigInteger = new BigInteger("1");

        BigInteger b128 = bigInteger.shiftLeft(128).subtract(f1);
        BigInteger b2048 = bigInteger.shiftLeft(2048).subtract(f1);
        BigInteger b1024 = bigInteger.shiftLeft(1024).subtract(f1);

        System.out.println(b128.toString(10));
        System.out.println(b128.toString(10).length());
        System.out.println(b1024.toString(10));
        System.out.println(b1024.toString(10).length());
        System.out.println(b2048.toString(10));
        System.out.println(b2048.toString(10).length());
    }


    @Test
    public void sk() {
        for (int i = 1; i < 10000; i++) {
            System.out.println(i);
        }
    }

}
